home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / msysjour / vol04 / 03 / debug386 / debugsrc.a86 < prev   
Text File  |  1987-07-28  |  22KB  |  675 lines

  1. NAME    ISR
  2.  
  3. EXTRN display_and_edit_regs:FAR
  4.  
  5. CODE SEGMENT PUBLIC 'CODE' 
  6. ASSUME CS:CODE
  7.  
  8. PUBLIC INT1_ISR, INT9_ISR, SYSREQ_ISR, ISR_common
  9. PUBLIC orig_INT1_ISR_ptr, orig_INT3_ISR_ptr, orig_SYSREQ_ISR_ptr
  10. PUBLIC orig_INT9_ISR_ptr
  11.  
  12. $EJECT
  13.  
  14. ;-----------------------------------------------------------------------------
  15. ;
  16. ;  This Assembly language module is composed of two interrupt service routines
  17. ;  (ISRs) and another block of code shared between the two ISRs.
  18. ;
  19. ;  The module is used to either awaken a register display/edit routine as a
  20. ;  result of an 80386 debug exception, or to awaken the display/edit routine
  21. ;  as a result of a user request to "pop-it-up" (via the SYSREQ key).
  22. ;
  23. ;  The first ISR, known as INT1_ISR, services the 80386 debug exception interrupt,
  24. ;  and then CALLs the common block of code, ISR_common.
  25. ;
  26. ;  ISR_common copies the current 80386 register image into a large data
  27. ;  structure and then CALLs the register display/edit routine (written in a 
  28. ;  higher-level language).
  29. ;
  30. ;  The second ISR, known as SYSREQ_ISR, is chained into the BIOS INT 15h
  31. ;  interrupt, and it merely awaits a SYSREQ key press (passing any other
  32. ;  INT 15h requests to the original INT 15h handler) before calling
  33. ;  ISR_common.
  34. ;
  35. ;  The display/edit routine (not shown in this article, but written in
  36. ;  PL/M-86) allows the user to examine and/or modify, by reading/altering
  37. ;  the aforementioned register image data structure, the normal 80386 
  38. ;  registers (in full 32 bit form), as well as the debug registers.
  39. ;
  40. ;-----------------------------------------------------------------------------
  41.  
  42. $EJECT
  43.  
  44. ;-----------------------------------------------------------------------------
  45. ;
  46. ;  Define structure/data area used to hold copies of the register images
  47. ;  as they exist when the INT 1 ISR is entered.
  48. ;
  49. ;  W A R N I N G :
  50. ;    The register ordering is  F I X E D ! ! !  The display_and_edit_regs
  51. ;    subroutine assumes a predefined ordering.
  52. ;
  53. ;  A L S O :
  54. ;    You probably noticed that each table entry is 32 bits long,
  55. ;    even though some registers are actually only 16 bits long (like CS).
  56. ;    The uniform entry size makes indexing into the table much easier
  57. ;    on the display routines.  If a register is only 16 bits wide, then
  58. ;    the high order 16 bits of its register image from the following structure
  59. ;    are wasted.  This is not a problem, since the program is not so large
  60. ;    that such wastage is critical.
  61. ;
  62. ;-----------------------------------------------------------------------------
  63. ISR_register_image    LABEL    DWORD
  64. ISR_DR0        DW    0            ;This register is 32 bits wide
  65.         DW    0
  66. ISR_DR1        DW    0            ;This register is 32 bits wide
  67.         DW    0
  68. ISR_DR2        DW    0            ;This register is 32 bits wide
  69.         DW    0
  70. ISR_DR3        DW    0            ;This register is 32 bits wide
  71.         DW    0
  72. ISR_DR6        DW    0            ;This register is 32 bits wide
  73.         DW    0
  74. ISR_DR7        DW    0            ;This register is 32 bits wide
  75.         DW    0
  76. ISR_CS        DW    0            ;This register is 16 bits wide
  77.         DW    ?            ;  (these 16 bits unused)
  78. ISR_EIP        DW    0            ;This register is 32 bits wide
  79.         DW    0
  80. ISR_SS        DW    0            ;This register is 16 bits wide
  81.         DW    ?            ;  (these 16 bits unused)
  82. ISR_ESP        DW    0            ;This register is 32 bits wide
  83.         DW    0
  84. ISR_DS        DW    0            ;This register is 16 bits wide
  85.         DW    ?            ;  (these 16 bits unused)
  86. ISR_ESI        DW    0            ;This register is 32 bits wide
  87.         DW    0
  88. ISR_ES        DW    0            ;This register is 16 bits wide
  89.         DW    ?            ;  (these 16 bits unused)
  90. ISR_EDI        DW    0            ;This register is 32 bits wide
  91.         DW    0
  92. ISR_EAX        DW    0            ;This register is 32 bits wide
  93.         DW    0
  94. ISR_EBX        DW    0            ;This register is 32 bits wide
  95.         DW    0
  96. ISR_ECX        DW    0            ;This register is 32 bits wide
  97.         DW    0
  98. ISR_EDX        DW    0            ;This register is 32 bits wide
  99.         DW    0
  100. ISR_EBP        DW    0            ;This register is 32 bits wide
  101.         DW    0
  102. ISR_FS        DW    0            ;This register is 16 bits wide
  103.         DW    ?            ;  (these 16 bits unused)
  104. ISR_GS        DW    0            ;This register is 16 bits wide
  105.         DW    ?            ;  (these 16 bits unused)
  106. ISR_CR0        DW    0            ;This register is 32 bits wide
  107.         DW    0
  108. ISR_EFLAGS    DW    0            ;This register is 32 bits wide
  109.           DW    0
  110. ;-----------------------------------------------------------------------------
  111. ;
  112. ;  The following space is allocated for the display_and_edit_regs routine,
  113. ;  but is not used by the ISRs.
  114. ;
  115. ;-----------------------------------------------------------------------------
  116. dr0_segment        DD    0
  117. dr0_offset        DD    0
  118. dr0_compare_value    DD    0
  119. dr0_compare_enable    DD    0
  120. dr1_segment        DD    0
  121. dr1_offset        DD    0
  122. dr1_compare_value    DD    0
  123. dr1_compare_enable    DD    0
  124. dr2_segment        DD    0
  125. dr2_offset        DD    0
  126. dr2_compare_value    DD    0
  127. dr2_compare_enable    DD    0
  128. dr3_segment        DD    0
  129. dr3_offset        DD    0
  130. dr3_compare_value    DD    0
  131. dr3_compare_enable    DD    0
  132. dr0_boolean        DD    0
  133. dr1_boolean        DD    0
  134. dr2_boolean        DD    0
  135. dr3_boolean        DD    0
  136.  
  137. $EJECT
  138.  
  139. ;-----------------------------------------------------------------------------
  140. ;
  141. ;  Allocate storage for INT 3 flag -- this flag is set/reset by the
  142. ;  register display routine, and indicates whether the ISR_common code
  143. ;  should trigger an INT3 shortly before RETing.
  144. ;
  145. ;-----------------------------------------------------------------------------
  146. INT3_flag        DB    ?
  147.  
  148.  
  149. ;-----------------------------------------------------------------------------
  150. ;
  151. ;  Allocat storage for the request flag -- we set this flag to indicate
  152. ;  to the register display routine whether we're calling it from
  153. ;  SYSREQ ("pop-up" request) or INT1 (debug exception has occurred).
  154. ;
  155. ;-----------------------------------------------------------------------------
  156. request_flag        DB    ?
  157. INT1_request        EQU    0
  158. SYSREQ_request        EQU    1
  159.  
  160.  
  161. ;-----------------------------------------------------------------------------
  162. ;
  163. ;  Define the values necessary for processing SYSREQ key presses.
  164. ;
  165. ;-----------------------------------------------------------------------------
  166. SYSREQ_key_pressed        EQU    08500h
  167. keyboard_status_port        EQU    064h
  168. input_buffer_full        EQU    002h
  169. enable_keyboard            EQU    0AEh
  170. PIC                EQU    020h
  171. EOI                EQU    020h
  172.  
  173.  
  174. ;-----------------------------------------------------------------------------
  175. ;
  176. ;  ISR local stack definition...
  177. ;
  178. ;-----------------------------------------------------------------------------
  179.         DW    512 DUP (0)
  180. ISR_stack    LABEL    WORD
  181.  
  182.  
  183. ;-----------------------------------------------------------------------------
  184. ;
  185. ;  Where we store the original SS:SP before we install the local stack.
  186. ;
  187. ;-----------------------------------------------------------------------------
  188. orig_ISR_stack_ptr    DW    ?
  189.             DW    ?
  190.  
  191.  
  192. ;-----------------------------------------------------------------------------
  193. ;
  194. ;  Storage for copy of local code segment value.
  195. ;
  196. ;-----------------------------------------------------------------------------
  197. local_data_seg        DW    CODE
  198.  
  199.  
  200.  
  201. ;-----------------------------------------------------------------------------
  202. ;
  203. ;  Define storage for the original interrupt service routine addresses
  204. ;  for the interrupts onto which we'll be chaining or installing ourselves.
  205. ;
  206. ;-----------------------------------------------------------------------------
  207. orig_INT1_ISR_ptr     DW    ?
  208.             DW    ?
  209. orig_INT3_ISR_ptr    DW    ?
  210.             DW    ?
  211. orig_INT9_ISR_ptr    DW    ?
  212.             DW    ?
  213. orig_SYSREQ_ISR_ptr    DW    ?
  214.             DW    ?
  215.  
  216.  
  217. ;-----------------------------------------------------------------------------
  218. ;
  219. ;  The following instruction prefix is 80386-specific.  It identifies the
  220. ;  subsequent instruction as one which uses a 32 bit operand size.  This
  221. ;  prefix allows us to create 80386 instructions using an 80286 assembler.
  222. ;
  223. ;-----------------------------------------------------------------------------
  224. operand_size_32_prefix    EQU    066H
  225.  
  226.  
  227. ;-----------------------------------------------------------------------------
  228. ;
  229. ;  Define stack frame which exists at the time the ISR_common is CALLed.
  230. ;
  231. ;-----------------------------------------------------------------------------
  232. ISR_stack_parm         STRUC
  233.     ISR_RTNA    DW    ?        ;Return address (to INT1_ISR or SYSREQ_ISR)
  234.     old_IP        DW    ?        ;CS:IP of code which was in progress at time
  235.     old_CS        DW    ?        ;  the debug exception occurred
  236.     old_FLAGS    DW    ?        ;State of the FLAGS at time of exception
  237. ISR_stack_parm         ENDS
  238.  
  239.  
  240. ;-----------------------------------------------------------------------------
  241. ;
  242. ;  Define flag which can be used to determine whether or not we're already
  243. ;  servicing an interrupt request (in other words, are we being re-entered ? )
  244. ;
  245. ;-----------------------------------------------------------------------------
  246. ISR_in_progress        DB    FALSE
  247. FALSE            EQU    0
  248. TRUE            EQU    0FFh
  249.  
  250. $EJECT
  251.  
  252. ;-----------------------------------------------------------------------------
  253. ;                                    
  254. ;        INT1 (80386 Debug Exception) Handler                
  255. ;                                    
  256. ;  This interrupt service routine can be entered as a result of    
  257. ;  one of the following conditions:                
  258. ;                                    
  259. ;        1 - instruction execution breakpoint            
  260. ;        2 - data access breakpoint                
  261. ;        3 - general detect fault                
  262. ;        4 - single step trap                    
  263. ;        5 - task switch breakpoint                
  264. ;
  265. ;  The ISR first ensures that it is not being re-entered, and then
  266. ;  CALLs ISR_common.
  267. ;                                    
  268. ;-----------------------------------------------------------------------------
  269. INT1_ISR    PROC    FAR
  270.  
  271.     JMP    INT1_start            ;Jump around header field
  272.     DB    'DAGGER'            ;This header is a "marker" used to 
  273.                         ;  determine if the ISR is already
  274.                         ;  installed
  275.  
  276. INT1_start:
  277.     PUSHF                    ;Save FLAGs
  278.     CMP    CS:ISR_in_progress,TRUE        ;Are we being re-entered?
  279.     JNE    not_being_reentered        ;NO
  280.     POPF                    ;YES, recover FLAGs,
  281.     STI                    ;  put interrupts back on,
  282.     IRET                    ;  and leave
  283.  
  284.  
  285. ;-----------------------------------------------------------------------------
  286. ;
  287. ;  Mark "in progress" flag so that we can't be re-entered
  288. ;
  289. ;-----------------------------------------------------------------------------
  290. not_being_reentered:
  291.     MOV    CS:ISR_in_progress,TRUE        ;Show "in progress"
  292.     MOV    CS:request_flag,INT1_request    ;Set flag indicating that this
  293.                         ;  INT occurred as a result of
  294.                         ;  an 80386 debug exception
  295.     POPF                    ;Recover FLAGS
  296.  
  297.     CALL    ISR_common            ;CALL common ISR code
  298.     IRET                    ;  and leave
  299.  
  300. INT1_ISR    ENDP
  301.  
  302. $EJECT
  303.  
  304. ;-----------------------------------------------------------------------------
  305. ;                                    
  306. ;        SYSREQ (System Request Key) Handler            
  307. ;                                    
  308. ;  This interrupt service routine can be entered as a result of    
  309. ;  one of the following conditions:                
  310. ;                                    
  311. ;        SYSREQ key pressed                    
  312. ;            OR                        
  313. ;        some other BIOS INT 15 request occurred            
  314. ;                                    
  315. ;  We will only CALL ISR_common if the ISR was entered as a result of a user
  316. ;  request to "pop-up" the register display/edit screen.
  317. ;  Otherwise, we simply chain onto the old BIOS INT 15 ISR.        
  318. ;                                    
  319. ;-----------------------------------------------------------------------------
  320. SYSREQ_ISR    PROC    FAR
  321.  
  322.     PUSHF                    ;Save FLAGS
  323.     CMP    AX,SYSREQ_key_pressed        ;Was the INT for SYSREQ key ?
  324.     JE    process_SYSREQ            ;YES -- do local processing
  325.  
  326. chain_to_original_ISR:
  327.     POPF                    ;NO, recover FLAGS
  328.     STI                    ;Interrupts back on
  329.     JMP    DWORD PTR CS:orig_SYSREQ_ISR_ptr ;Chain on to original SYSREQ ISR
  330.  
  331. process_SYSREQ:
  332.     PUSH    AX                ;Save AX
  333.     MOV    AL,EOI                
  334.     OUT    PIC,AL                ;Issue End-of-Interrupt to PIC
  335. await_keybd_controller:
  336.     IN    AL,keyboard_status_port        ;Get keyboard controller status
  337.     TEST    AL,input_buffer_full        ;Keyboard controller ready to accept command ?
  338.     JNZ    await_keybd_controller        ;NO
  339.     MOV    AL,enable_keyboard        ;YES
  340.     OUT    keyboard_status_port,AL        ;Re-enable keyboard
  341.     POP    AX                ;  recover AX
  342.     POPF                    ;  recover FLAGS,
  343.  
  344. ;-----------------------------------------------------------------------------
  345. ;
  346. ;  IF we're being re-entered, then simply chain to original ISR.
  347. ;
  348. ;-----------------------------------------------------------------------------
  349.     PUSHF                    ;Save flags
  350.     CMP    CS:ISR_in_progress,TRUE        ;Are we being re-entered?
  351.     JNE    SYSREQ_not_being_reentered    ;NO
  352.     JMP    chain_to_original_ISR        ;Chain to original ISR
  353.  
  354. ;-----------------------------------------------------------------------------
  355. ;
  356. ;  ELSE:  mark "in progress" flag so that we can't be re-entered
  357. ;
  358. ;-----------------------------------------------------------------------------
  359. SYSREQ_not_being_reentered:
  360.     MOV    CS:ISR_in_progress,TRUE        ;Show "in progress"
  361.     MOV    CS:request_flag,SYSREQ_request    ;Set flag indicating that this
  362.                         ;  INT occurred as a result of
  363.                         ;  a user request to "pop-up"
  364.                         ;  the display/edit routine
  365.     POPF                    ;Recover FLAGS
  366.  
  367.     CALL    ISR_common            ;  CALL common ISR code,
  368.     JMP    DWORD PTR CS:orig_SYSREQ_ISR_ptr ;  and then JMP to original INT 15h ISR
  369.  
  370. SYSREQ_ISR    ENDP
  371.  
  372. $EJECT
  373.  
  374. INT9_ISR    PROC    FAR
  375.  
  376.     JMP    DWORD PTR CS:orig_INT9_ISR_ptr
  377.  
  378. INT9_ISR    ENDP
  379.  
  380. $EJECT
  381.  
  382. ISR_common    PROC    NEAR
  383.  
  384. ;-----------------------------------------------------------------------------
  385. ;
  386. ;  Common interrupt service routine code (shared by INT1_ISR and SYSREQ_ISR)
  387. ;
  388. ;  This common block of code simply copies the current register state into
  389. ;  the large data structure described earlier.  The address of the data
  390. ;  structure is passed to the display/edit registers routine, which is a
  391. ;  higher-level language subroutine that allows the user to edit the
  392. ;  normal 80386 registers, as well as edit the debug registers.
  393. ;
  394. ;-----------------------------------------------------------------------------
  395.     STI                    ;Interrupts back on
  396.  
  397. ;-----------------------------------------------------------------------------
  398. ;
  399. ;  Put EBP into data structure. 
  400. ;  Put EAX into data structure.
  401. ;  Then get EFLAGS into data structure via EAX.  FLAGS (low word of EFLAGS)
  402. ;  were pushed onto the stack by the CPU when the INT occurred.  We'll
  403. ;  just OR the FLAGS (low 16 bits of EFLAGS) from the stack with the high word 
  404. ;  of current EFLAGS.
  405. ;
  406. ;-----------------------------------------------------------------------------
  407.     DB    operand_size_32_prefix
  408.     MOV    CS:ISR_EBP,BP            ;EBP into global structure
  409.  
  410.     DB    operand_size_32_prefix        
  411.     MOV    BP,SP                ;EBP = current ESP
  412.  
  413.     DB    operand_size_32_prefix
  414.     MOV    CS:ISR_EAX,AX            ;EAX into global structure
  415.  
  416.     DB    operand_size_32_prefix
  417.     PUSHF                    ;PUSH EFLAGS
  418.     DB    operand_size_32_prefix
  419.     POP    AX                ;POP EAX (high word of EAX has high word of EFLAGS)
  420.     MOV    AX,[BP].old_FLAGS        ;Get FLAGS from stack into low word of EAX
  421.     DB    operand_size_32_prefix
  422.     MOV    CS:ISR_EFLAGS,AX         ;EFLAGS into global structure
  423.  
  424. $EJECT
  425.  
  426. ;-----------------------------------------------------------------------------
  427. ;
  428. ;  Get CS:IP from stack (placed there by 80386 when INT 1 occurred).
  429. ;
  430. ;-----------------------------------------------------------------------------
  431.     MOV    AX,[BP].old_CS            ;Get CS from stack
  432.     MOV    CS:ISR_CS,AX            ;CS into global structure
  433.     DB    operand_size_32_prefix
  434.     SUB    AX,AX                ;Clear high word of EAX
  435.     MOV    AX,[BP].old_IP            ;Get IP from stack into low word of EAX
  436.     DB    operand_size_32_prefix
  437.     MOV    CS:ISR_EIP,AX            ;EIP into global structure
  438.  
  439. ;-----------------------------------------------------------------------------
  440. ;
  441. ;  Copy the rest of the registers into the data structure.
  442. ;
  443. ;-----------------------------------------------------------------------------
  444.     MOV    CS:ISR_DS,DS            ;DS
  445.  
  446.     DB    operand_size_32_prefix
  447.     MOV    CS:ISR_ESI,SI            ;ESI
  448.  
  449.     MOV    CS:ISR_ES,ES            ;ES
  450.  
  451.     DB    operand_size_32_prefix
  452.     MOV    CS:ISR_EDI,DI            ;EDI
  453.  
  454.     DB    operand_size_32_prefix
  455.     MOV    CS:ISR_EBX,BX            ;EBX
  456.  
  457.     DB    operand_size_32_prefix
  458.     MOV    CS:ISR_ECX,CX            ;ECX
  459.  
  460.     DB    operand_size_32_prefix
  461.     MOV    CS:ISR_EDX,DX            ;EDX
  462.  
  463.     DB    08Ch,0E0h            ;FS
  464.     MOV    CS:ISR_FS,AX            
  465.  
  466.     DB    08Ch,0E8h            ;GS
  467.     MOV    CS:ISR_GS,AX            
  468.  
  469.     DB    00Fh,020h,0C0h            ;CR0
  470.     DB    operand_size_32_prefix
  471.     MOV    CS:ISR_CR0,AX            
  472.  
  473.     DB    0Fh,021h,0C0h            ;DR0
  474.     DB    operand_size_32_prefix
  475.     MOV    CS:ISR_DR0,AX            
  476.  
  477.     DB    0Fh,021h,0C8h            ;DR1
  478.     DB    operand_size_32_prefix
  479.     MOV    CS:ISR_DR1,AX            
  480.  
  481.     DB    0Fh,021h,0D0h            ;DR2
  482.     DB    operand_size_32_prefix
  483.     MOV    CS:ISR_DR2,AX            
  484.  
  485.     DB    0Fh,021h,0D8h            ;DR3
  486.     DB    operand_size_32_prefix
  487.     MOV    CS:ISR_DR3,AX            
  488.  
  489.     DB    0Fh,021h,0F0h            ;DR6
  490.     DB    operand_size_32_prefix
  491.     MOV    CS:ISR_DR6,AX            
  492.  
  493.     DB    0Fh,021h,0F8h            ;DR7
  494.     DB    operand_size_32_prefix
  495.     MOV    CS:ISR_DR7,AX            
  496.  
  497. $EJECT
  498.  
  499. ;-----------------------------------------------------------------------------
  500. ;
  501. ;  Save original SS:SP into save area and also into the global structure, 
  502. ;  and then create a new SS:SP so that we can CALL a stack-intensive 
  503. ;  P/LM-86 routine.
  504. ;
  505. ;-----------------------------------------------------------------------------
  506.     DB    operand_size_32_prefix
  507.     ADD    BP,SIZE ISR_stack_parm        ;Adjust EBP (which is a copy
  508.                         ;  of original ESP) so that it
  509.                         ;  reflects original state of
  510.                         ;  ESP at the time INT occurred
  511.     DB    operand_size_32_prefix
  512.     MOV    CS:ISR_ESP,BP            ;ESP into global structure
  513.     MOV    CS:ISR_SS,SS            ;SS into global structure
  514.  
  515.     MOV    CS:orig_ISR_stack_ptr,SP    ;Save SP into local storage
  516.     MOV    CS:orig_ISR_stack_ptr + 2,SS    ;Save SS into local storage
  517.  
  518.     CLI                    ;Clear INTs while working on stack regs
  519.     MOV    SS,CS:local_data_seg        ;New SS
  520.     LEA    SP,ISR_stack            ;New SP
  521.     STI                    ;Restore INTs
  522.  
  523. ;-----------------------------------------------------------------------------
  524. ;
  525. ;  CALL the PL/M-86 procedure responsible for displaying and processing
  526. ;  the information we've just put into the data structure.
  527. ;  The PL/M routine will read and display the register state (as shown
  528. ;  in the data structure), and will allow the user to indirectly modify the
  529. ;  registers (including the debug registers) via edits to that same
  530. ;  structure.
  531. ;  When the display/edit routine RETurns, we'll copy the register image
  532. ;  back into the 80386 registers.
  533. ;
  534. ;-----------------------------------------------------------------------------
  535.     LEA    AX,ISR_register_image        ;Pass the address of the 
  536.     PUSH    CS                ;  register image
  537.     PUSH    AX                ;  as a pointer on the stack
  538.     LEA    AX,INT3_flag            ;Pass the addrs of INT3 flag
  539.     PUSH    CS                ;  so that the display/edit routine
  540.     PUSH    AX                ;  can set/reset it as the user so desires
  541.     MOV    AL,CS:request_flag        ;Pass the request type flag so
  542.     PUSH    AX                ;  that the display/edit routine
  543.                         ;  can determine whether it was called
  544.                         ;  as the result of an INT 1 or SYSREQ
  545.     CALL    display_and_edit_regs        ;CALL the P/LM-86 PROCedure
  546.  
  547. $EJECT
  548.  
  549. ;-----------------------------------------------------------------------------
  550. ;
  551. ;  Transfer the edited register images from the global structure 
  552. ;  back into the 80386 registers.
  553. ;
  554. ;-----------------------------------------------------------------------------
  555.     DB    operand_size_32_prefix
  556.     MOV    BX,CS:ISR_EBX            ;EBX
  557.  
  558.     DB    operand_size_32_prefix
  559.     MOV    CX,CS:ISR_ECX            ;ECX
  560.  
  561.     DB    operand_size_32_prefix
  562.     MOV    DX,CS:ISR_EDX            ;EDX
  563.  
  564.     DB    operand_size_32_prefix
  565.     MOV    SI,CS:ISR_ESI            ;ESI
  566.  
  567.     DB    operand_size_32_prefix
  568.     MOV    DI,CS:ISR_EDI            ;EDI
  569.  
  570.     DB    operand_size_32_prefix
  571.     MOV    BP,CS:ISR_EBP            ;EBP
  572.  
  573.     MOV    ES,CS:ISR_ES            ;ES
  574.  
  575.     MOV    DS,CS:ISR_DS            ;DS
  576.  
  577.     MOV    AX,CS:ISR_FS
  578.     DB    08Eh,0E0h            ;MOV FS,AX
  579.  
  580.     MOV    AX,CS:ISR_GS
  581.     DB    08Eh,0E8h            ;MOV GS,AX
  582.  
  583.     DB    operand_size_32_prefix
  584.     MOV    AX,CS:ISR_CR0
  585.     DB    00Fh,022h,0C0h            ;MOV CR0,EAX
  586.  
  587.     DB    operand_size_32_prefix
  588.     MOV    AX,CS:ISR_DR0
  589.     DB    00Fh,023h,0C0h            ;MOV DR0,EAX
  590.  
  591.     DB    operand_size_32_prefix
  592.     MOV    AX,CS:ISR_DR1
  593.     DB    00Fh,023h,0C8h            ;MOV DR1,EAX
  594.  
  595.     DB    operand_size_32_prefix
  596.     MOV    AX,CS:ISR_DR2
  597.     DB    00Fh,023h,0D0h            ;MOV DR2,EAX
  598.  
  599.     DB    operand_size_32_prefix
  600.     MOV    AX,CS:ISR_DR3
  601.     DB    00Fh,023h,0D8h            ;MOV DR3,EAX
  602.  
  603. ;-----------------------------------------------------------------------------
  604. ;
  605. ;  Clear out DR6 -- all bits in that reg must be reset after each
  606. ;  INT 1  (ignore whatever is currently sitting in the DR6 register image).
  607. ;
  608. ;-----------------------------------------------------------------------------
  609.     DB    operand_size_32_prefix
  610.     SUB    AX,AX                ;SUB EAX,EAX
  611.     DB    00Fh,023h,0F0h            ;MOV DR6,EAX
  612.  
  613.     DB    operand_size_32_prefix
  614.     MOV    AX,CS:ISR_DR7            ;MOV EAX,CS:ISR_DR7
  615.     DB    00Fh,023h,0F8h            ;MOV DR7,EAX
  616.  
  617.     DB    operand_size_32_prefix
  618.     MOV    AX,CS:ISR_EFLAGS        ;MOV EAX,CS:ISR_EFLAGS
  619.     DB    operand_size_32_prefix
  620.     PUSH    AX                ;PUSH EAX
  621.     DB    operand_size_32_prefix
  622.     POPF                    ;POP EFLAGS
  623.  
  624.     DB    operand_size_32_prefix
  625.     MOV    AX,CS:ISR_EAX            ;MOV EAX,CS:ISR_EAX
  626.  
  627. $EJECT
  628.  
  629. ;-----------------------------------------------------------------------------
  630. ;
  631. ;  Clean up stack.
  632. ;
  633. ;-----------------------------------------------------------------------------
  634.     CLI                    ;Clear INTs while working on stack
  635.     MOV    SS,CS:orig_ISR_stack_ptr + 2    ;Get original SS
  636.     MOV    SP,CS:orig_ISR_stack_ptr    ;Get original SP
  637.     MOV    CS:ISR_in_progress,FALSE    ;Show "no longer in progress"
  638.  
  639. ;-----------------------------------------------------------------------------
  640. ;
  641. ;  Issue an INT3 (old-style debugger interrupt) if user so directed.
  642. ;  In that fashion, we can trigger a "real" debugger (presumably one which
  643. ;  will allow us to examine/modify memory and display symbol information).
  644. ;  We can merely get rid of the local caller's return address (SYSREQ_ISR or INT1_ISR),
  645. ;  and then "JMP" directly to the original INT3 ISR.  Since our code
  646. ;  was entered as a result of an INT1, then the stack will already be
  647. ;  set up such that the INT3 routine has only to execute an IRET.
  648. ;
  649. ;-----------------------------------------------------------------------------
  650.     PUSHF
  651.     CMP    CS:INT3_flag,0            ;Did the user want an INT3 ?
  652.     JZ    ISR_common_RET            ;NO
  653.     POPF                    ;YES, recover flags,
  654.     ADD    SP,2                ;  pop-off the local
  655.                         ;  caller's return address
  656.     PUSH    BP                ;Save reg
  657.     MOV    BP,SP                ;Get stack ptr
  658.     INC    WORD PTR [BP + 2]        ;Adjust IP on stack such that
  659.                         ;  the INT3 handler can DEC to
  660.                         ;  adjust for the "INT3"
  661.     POP    BP                ;Recover reg
  662.     STI                    ;Put interrupts back on,
  663.     JMP    DWORD PTR CS:orig_INT3_ISR_ptr    ;  and then "JMP" to the 
  664.                         ;  original INT3 ISR
  665.     
  666. ISR_common_RET:
  667.     POPF                    ;Recover flags
  668.     STI                    ;Interrupts back on
  669.     RET
  670.  
  671. ISR_common    ENDP
  672.  
  673. CODE    ENDS
  674. END
  675.